from PyQt5.QtCore import QObject, pyqtSignal
from typing import List, Optional
import numpy as np

from components.detector import YOLOv8Detector
from components.image_processor import ImageProcessor
from components.async_worker import DetectionWorker
from models.data_models import DetectionResult, ImageInfo

class MainController(QObject):
    """主控制器组件"""
    
    # 信号定义
    detection_completed = pyqtSignal(int, DetectionResult)  # 检测完成
    batch_progress_updated = pyqtSignal(int, int)  # 批量处理进度
    batch_completed = pyqtSignal()  # 批量处理完成
    error_occurred = pyqtSignal(str)  # 错误信号
    status_updated = pyqtSignal(str)  # 状态更新
    
    def __init__(self):
        super().__init__()
        
        # 初始化组件
        self.detector = YOLOv8Detector()
        self.image_processor = ImageProcessor()
        self.detection_worker = None
        
        # 连接信号
        self._connect_signals()
    
    def _connect_signals(self):
        """连接各组件信号"""
        self.image_processor.image_loaded.connect(self._on_image_loaded)
        self.image_processor.batch_loaded.connect(self._on_batch_loaded)
    
    def load_model(self, model_path: str) -> bool:
        """加载检测模型"""
        try:
            self.detector.load_model(model_path)
            self.status_updated.emit("模型加载成功")
            return True
        except Exception as e:
            error_msg = f"模型加载失败: {e}"
            self.error_occurred.emit(error_msg)
            return False
    
    def open_single_image(self, image_path: str) -> bool:
        """打开单张图像"""
        try:
            image = self.image_processor.load_image(image_path)
            if image is not None:
                self.status_updated.emit(f"图像加载成功: {image_path}")
                return True
            else:
                self.error_occurred.emit("图像加载失败")
                return False
        except Exception as e:
            self.error_occurred.emit(f"打开图像失败: {e}")
            return False
    
    def open_batch_images(self, folder_path: str) -> bool:
        """批量打开图像"""
        try:
            loaded_paths = self.image_processor.load_batch(folder_path)
            if loaded_paths:
                self.status_updated.emit(f"批量加载完成，共 {len(loaded_paths)} 张图像")
                return True
            else:
                self.error_occurred.emit("未找到有效图像文件")
                return False
        except Exception as e:
            self.error_occurred.emit(f"批量加载失败: {e}")
            return False
    
    def detect_current_image(self) -> bool:
        """检测当前图像"""
        if not self.detector.is_loaded:
            self.error_occurred.emit("请先加载模型")
            return False
        
        current_image = self.image_processor.get_current_image()
        current_info = self.image_processor.get_current_image_info()
        
        if current_image is None or current_info is None:
            self.error_occurred.emit("没有可检测的图像")
            return False
        
        try:
            result = self.detector.detect(current_image, current_info.path)
            
            # 更新图像信息
            current_info.is_processed = True
            current_info.detection_result = result
            
            # 发送检测完成信号
            self.detection_completed.emit(self.image_processor.current_index, result)
            self.status_updated.emit(f"检测完成，发现 {result.count} 只天牛")
            return True
            
        except Exception as e:
            self.error_occurred.emit(f"检测失败: {e}")
            return False
    
    def detect_batch_async(self, indices: List[int] = None) -> bool:
        """异步批量检测"""
        if not self.detector.is_loaded:
            self.error_occurred.emit("请先加载模型")
            return False
        
        if not self.image_processor.image_queue:
            self.error_occurred.emit("没有可检测的图像")
            return False
        
        # 停止之前的工作线程
        if self.detection_worker and self.detection_worker.isRunning():
            self.detection_worker.stop()
            self.detection_worker.wait()
        
        # 创建新的工作线程
        self.detection_worker = DetectionWorker(self.detector)
        self.detection_worker.set_batch_task(self.image_processor.image_queue, indices)
        
        # 连接信号
        self.detection_worker.detection_finished.connect(self._on_detection_finished)
        self.detection_worker.batch_progress.connect(self._on_batch_progress)
        self.detection_worker.batch_finished.connect(self._on_batch_finished)
        self.detection_worker.error_occurred.connect(self.error_occurred)
        
        # 启动线程
        self.detection_worker.start()
        self.status_updated.emit("开始批量检测...")
        return True
    
    def set_current_image(self, index: int) -> bool:
        """设置当前图像"""
        return self.image_processor.set_current_index(index)
    
    def get_current_image(self) -> Optional[np.ndarray]:
        """获取当前图像"""
        return self.image_processor.get_current_image()
    
    def get_current_image_info(self) -> Optional[ImageInfo]:
        """获取当前图像信息"""
        return self.image_processor.get_current_image_info()
    
    def get_image_queue(self) -> List[ImageInfo]:
        """获取图像队列"""
        return self.image_processor.image_queue
    
    def set_confidence_threshold(self, threshold: float):
        """设置置信度阈值"""
        self.detector.set_confidence_threshold(threshold)
    
    def clear_images(self):
        """清空图像队列"""
        # 停止工作线程
        if self.detection_worker and self.detection_worker.isRunning():
            self.detection_worker.stop()
            self.detection_worker.wait()
        
        self.image_processor.clear_queue()
        self.status_updated.emit("图像队列已清空")
    
    def _on_image_loaded(self, image_path: str):
        """图像加载完成回调"""
        pass
    
    def _on_batch_loaded(self, count: int):
        """批量加载完成回调"""
        pass
    
    def _on_detection_finished(self, index: int, result: DetectionResult):
        """单张检测完成回调"""
        self.detection_completed.emit(index, result)
    
    def _on_batch_progress(self, current: int, total: int):
        """批量处理进度回调"""
        self.batch_progress_updated.emit(current, total)
    
    def _on_batch_finished(self):
        """批量处理完成回调"""
        self.batch_completed.emit()
        self.status_updated.emit("批量检测完成")
